package org.jet.emall.prod.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

import org.jet.emall.common.constant.CartItemSelectedValue;
import org.jet.emall.common.restful.result.CommonPage;
import org.jet.emall.prod.custom.dao.ProductDao;
import org.jet.emall.prod.custom.po.AttrPO;
import org.jet.emall.prod.custom.po.CartItemPO;
import org.jet.emall.prod.custom.po.SpecPO;
import org.jet.emall.prod.dto.*;
import org.jet.emall.prod.po.*;
import org.jet.emall.prod.service.mp.*;
import org.jet.emall.prod.transfer.CartDtoTransfer;
import org.jet.emall.prod.transfer.CategoryDtoTransfer;
import org.jet.emall.prod.transfer.SkuDtoTransfer;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * @author xiaozai
 * @version 1.0
 * @date 2020-04-25 12:07
 */

@Service
public class CustomProductServiceImpl implements CustomProductService {
    @Autowired
    private ISkuViewService skuViewService;
    @Autowired
    private ISpuViewService spuViewService;

    @Autowired
    private IProdSkuService prodSkuService;

    @Autowired
    private IProdSkuImageService prodSkuImageService;

    @Autowired
    private ProductDao productDao;
    @Autowired
    private IProdCateService prodCateService;

    @Autowired
    private IProdSpuImageService prodSpuImageService;

    @Autowired
    private IOrderCartService orderCartService;

    @Autowired
    private IOrderCartItemService orderCartItemService;

    @Override
    public CommonPage<SkuDTO> page(String query, Integer pageNum, Integer pageSize) {
        Page<SkuView> page = skuViewService.page(new Page<SkuView>().setSize(pageSize)
                        .setCurrent(pageNum),
                new QueryWrapper<SkuView>().groupBy("spu_id").like(StringUtils.isNotBlank(query),"name",query));

        return new CommonPage<SkuDTO>().setTotalPage(page.getPages())
                .setTotal(page.getTotal())
                .setPageSize(page.getSize())
                .setPageNum(page.getCurrent())
                .setList(SkuDtoTransfer.INSTANCE.toDtoList(page.getRecords()));
    }

    @Override
    public CommonPage<SkuDTO> page2(Long cateId, Long brandId, String query, Integer pageNum, Integer pageSize) {

        QueryWrapper<SkuView> wrapper = new QueryWrapper<>();
        wrapper.groupBy("spu_id")
                .like(StringUtils.isNotBlank(query),"name",query);
        if(cateId!=null){
            wrapper.eq("cate_id",cateId);
        }
        if(brandId!=null){
            wrapper.eq("brand_id",brandId);
        }
        Page<SkuView> page = skuViewService.page(new Page<SkuView>().setSize(pageSize)
                        .setCurrent(pageNum), wrapper);

        return new CommonPage<SkuDTO>().setTotalPage(page.getPages())
                .setTotal(page.getTotal())
                .setPageSize(page.getSize())
                .setPageNum(page.getCurrent())
                .setList(SkuDtoTransfer.INSTANCE.toDtoList(page.getRecords()));
    }

    @Override
    public SpuDetailsDTO getSpuDetails(Long id) {
        SpuView spuView = spuViewService.getOne(new QueryWrapper<SpuView>().eq("id",id));
        if(spuView==null){
            return null;
        }
        SpuDetailsDTO spu = new SpuDetailsDTO();
        spu.setId(spuView.getId());
        spu.setCate1Name(spuView.getCate1Name());
        spu.setCate2Name(spuView.getCate2Name());
        spu.setCate3Name(spuView.getCate3Name());
        spu.setBrief(spuView.getBrief());
        spu.setName(spuView.getName());
        spu.setCode(spuView.getCode());
        spu.setBrand(spuView.getBrandName());


        List<ProdSku> list = prodSkuService.list(new QueryWrapper<ProdSku>().eq("spu_id", id));
        List<SkuDetailsDTO> dtoList = new LinkedList<>();
        for(ProdSku sku : list){
            SkuDetailsDTO dto = new SkuDetailsDTO();
            dto.setCode(sku.getCode());
            dto.setCount(sku.getCount());
            dto.setId(sku.getId());
            dto.setName(sku.getName());
            dto.setPrice(sku.getPrice());
            List<AttrPO> attrPOList = productDao.selectAttrsOfSku(sku.getId());
            List<AttrDTO> attrs = SkuDtoTransfer.INSTANCE.toAttrDtoList(attrPOList);
            List<SpecPO> specPOList = productDao.selectSpecsOfSku(sku.getId());

            List<ProdSkuImage> skuImages = prodSkuImageService.list(new QueryWrapper<ProdSkuImage>().eq("sku_id", sku.getId()));
            List<SkuImageDTO> images = SkuDtoTransfer.INSTANCE.toImageDtoList(skuImages);
            dto.setAttrs(attrs);

            Map<String,List<SpecDTO>> map = new TreeMap<>();
            specPOList.forEach(specPO -> {
                SpecDTO spec = new SpecDTO();
                spec.setName(specPO.getSpecName());
                spec.setValue(specPO.getSpecOptionValue());
                List<SpecDTO> specDTOList = map.get(specPO.getGroupName());
                if(specDTOList==null){
                    specDTOList = new LinkedList<>();
                    map.put(specPO.getGroupName(),specDTOList);
                }
                specDTOList.add(spec);
            });
            List<SpecGroupDTO> specGroups = new LinkedList<>();
            map.forEach((key,value)->{
                SpecGroupDTO groupDTO = new SpecGroupDTO();
                groupDTO.setGroup(key);
                groupDTO.setSpecsList(value);
                specGroups.add(groupDTO);
            });

            dto.setSpecGroups(specGroups);

            dto.setImages(images);

            dtoList.add(dto);
        }
        spu.setSkus(dtoList);
        List<ProdSpuImage> spuImages = prodSpuImageService.list(new QueryWrapper<ProdSpuImage>().eq("spu_id", id));
        List<String> images = new LinkedList<>();
        spuImages.forEach(prodSpuImage -> {
            images.add(prodSpuImage.getImage());
        });
        spu.setImages(images);
        return spu;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public CartDTO getCart(Long customerId) {
        OrderCart cart = orderCartService.getOne(new QueryWrapper<OrderCart>().eq("customer_id", customerId));

        if(cart==null){
            cart = new OrderCart();
            cart.setCustomerId(customerId);
            orderCartService.save(cart);
            return new CartDTO().setId(cart.getId());
        }
        return getCartById(cart.getId());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public CartDTO updateCart(Long cartId, Long skuId, Integer count) {
        OrderCart cart = orderCartService.getById(cartId);
        if(cart==null){
            return null;
        }
        OrderCartItem cartItem = orderCartItemService.getOne(new QueryWrapper<OrderCartItem>().eq("cart_id", cartId)
                .eq("sku_id", skuId));
        if(cartItem==null && count>0){

            cartItem = new OrderCartItem().setCartId(cartId)
                        .setSkuId(skuId)
                        .setCount(count);
            orderCartItemService.save(cartItem);
        }else{

            if(count<=0){
                orderCartItemService.removeById(cartItem.getId());
            }else {
                cartItem.setCount(count);
                orderCartItemService.updateById(cartItem);
            }
        }
        return getCartById(cartId);
    }

    @Override
    public CartDTO deleteCartItems(Long cartId, List<Long> cartItemIds) {
        if(cartItemIds!=null&& !cartItemIds.isEmpty()) {
            orderCartItemService.removeByIds(cartItemIds);
        }
        return getCartById(cartId);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public CartDTO updateCartItemsSelected(Long cartId, List<Long> cartItemIds) {
        orderCartItemService.update(new UpdateWrapper<OrderCartItem>().eq("cart_id",cartId).set("selected", CartItemSelectedValue.UNSELECTED));
        if(cartItemIds!=null && !cartItemIds.isEmpty()) {
            orderCartItemService.update(new UpdateWrapper<OrderCartItem>().in("id", cartItemIds).set("selected", CartItemSelectedValue.SELECTED));
        }
        return getCartById(cartId);
    }

    @Override
    public List<CategoryDTO> getProductCategories() {

        List<ProdCate> list = prodCateService.list();
        List<CategoryDTO> dtoList = CategoryDtoTransfer.INSTANCE.toDtoList(list);
        List<CategoryDTO> result = makeTree(dtoList);
        return result;
    }

    @Override
    public SpuDetailsDTO getSpuDetailsBySkuId(Long id) {
        ProdSku sku = prodSkuService.getById(id);
        return  getSpuDetails(sku.getSpuId());
    }

    private List<CategoryDTO> makeTree(List<CategoryDTO> dtoList){
        Map<Integer,CategoryDTO> map = new HashMap<>(64);
        dtoList.forEach(dto->{
            map.put(dto.getId(),dto);
        });
        map.forEach((key,value)->{
            if(value.getPid()!=0) {
                CategoryDTO p = map.get(value.getPid());
                List<CategoryDTO> children = p.getChildren();
                if(children==null){
                    children = new LinkedList<>();
                    p.setChildren(children);
                }
                children.add(value);
            }
        });
        dtoList.removeIf(v-> v.getPid()!=0);
        map.clear();
        return dtoList;
    }

    /**
     *  根据id查找购物车
     * @param id
     * @return
     */
    private CartDTO getCartById(Long id){
        List<CartItemPO> cartItemList = productDao.selectCartItemsOfCart(id);
        CartDTO cartDTO = new CartDTO();
        cartDTO.setId(id).setItems(CartDtoTransfer.INSTANCE.toDtoList(cartItemList));
        return cartDTO;
    }
}
